﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using AzukiMap.Layer;
using AzukiMap.Map;
using AzukiMap;
using Geotools.Geometries;
using AzukiMap.Tools;

namespace AzukiMapUI
{
    public partial class LayerVisibility : UserControl
    {
        bool _isInited = false;
        ILayer _layer;
        GeometryUtil _geomUtil;

        public ILayer Layer
        {
            get { return _layer; }
            set { 
                _layer = value;
                SetForm();
            }
        }

        public LayerVisibility()
        {
            InitializeComponent();
            _isInited = true;
            _geomUtil = new GeometryUtil();
        }

        void SetForm()
        {
            //TbOpacity.Text = (_layer.MapCanvas.Opacity * 100).ToString();
            TbOpacity.Text = (_layer.Opacity * 100).ToString();

            if (_layer.MaxScale == AzukiMapSettings.DEFAULT_MAXSCALE)
            {
                ChkMaxScale.IsChecked = false;
            }
            else
            {
                ChkMaxScale.IsChecked = true;
            }
            TbMaxScale.Text = _layer.MaxScale.ToString();

            if (_layer.MinScale == AzukiMapSettings.DEFAULT_MINSCALE)
            {
                ChkMinScale.IsChecked = false;
            }
            else
            {
                ChkMinScale.IsChecked = true;
            }
            TbMinScale.Text = _layer.MinScale.ToString();

            if (_layer.MaxExtent != null)
            {
                ChkClipping.IsChecked = true;
                GTCoordinate MaxExtentBl = _geomUtil.GetExtentPoint(_layer.MaxExtent, ExtentOrder.BOTTOM_LEFT);
                GTCoordinate MaxExtentTr = _geomUtil.GetExtentPoint(_layer.MaxExtent, ExtentOrder.TOP_RIGHT);
                TbMaxLon.Text = MaxExtentTr.X.ToString();
                TbMaxLat.Text = MaxExtentTr.Y.ToString();
                TbMinLon.Text = MaxExtentBl.X.ToString();
                TbMinLat.Text = MaxExtentBl.Y.ToString();
            }
            CheckAll();
        }

        public void SetAll()
        {
            //_layer.MapCanvas.Opacity = double.Parse(TbOpacity.Text) / 100;
            _layer.Opacity = double.Parse(TbOpacity.Text) / 100;

            if ((bool)ChkMinScale.IsChecked)
            {
                _layer.MinScale = double.Parse(TbMinScale.Text);
            }
            else
            {
                _layer.MinScale = AzukiMapSettings.DEFAULT_MINSCALE;
            }

            if ((bool)ChkMaxScale.IsChecked)
            {
                _layer.MaxScale = double.Parse(TbMaxScale.Text);
            }
            else
            {
                _layer.MaxScale = AzukiMapSettings.DEFAULT_MAXSCALE;
            }

            if ((bool)ChkClipping.IsChecked)
            {
                if ((bool)RbByExtent.IsChecked)
                {
                    double trX = double.Parse(TbMaxLon.Text);
                    double trY = double.Parse(TbMaxLat.Text);
                    double blX = double.Parse(TbMinLon.Text);
                    double blY = double.Parse(TbMinLat.Text);
                    GTPolygon extent = _geomUtil.CreateExtentPolygon(blX, blY, trX, trY);
                    _layer.MaxExtent = extent;
                }
                else if ((bool)RbByPolygon.IsChecked)
                {
                    // TODO: not yet implemented.
                }
            }
        }

        #region input check
        bool CheckAll()
        {
            bool isOk1 = CheckOpacity();
            bool isOk2 = CheckMaxMinScale();
            bool isOk3 = CheckMinMaxPoint();

            return (isOk1 && isOk2 && isOk3);
        }

        bool CheckOpacity()
        {
            return FormInputControl.CheckNumberBetween(TbOpacity.Text, IconErrorOpacity, 0, 100);
        }

        bool CheckMaxScale()
        {
            bool useMaxScale = (bool)ChkMaxScale.IsChecked;
            if (useMaxScale)
            {
                return FormInputControl.CheckPositiveDouble(TbMaxScale.Text, IconErrorMaxScale);
            }
            else
            {
                return true;
            }
        }

        bool CheckMinScale()
        {
            bool useMinScale = (bool)ChkMinScale.IsChecked;
            if (useMinScale)
            {
                return FormInputControl.CheckPositiveDouble(TbMinScale.Text, IconErrorMinScale);
            }
            else
            {
                return true;
            }
        }

        bool CheckMaxMinScale()
        {
            bool useMaxScale = (bool)ChkMaxScale.IsChecked;
            bool useMinScale = (bool)ChkMinScale.IsChecked;

            if (!CheckMaxScale())
            {
                return false;
            }
            if (!CheckMinScale())
            {
                return false;
            }
            if (useMaxScale && useMinScale)
            {
                double min = double.Parse(TbMinScale.Text);
                double max = double.Parse(TbMaxScale.Text);
                // values in textboxes are denominator.
                if (min > max)
                {
                    return true;
                }
                else
                {
                    FormInputControl.ShowElement(IconErrorMaxScale);
                    FormInputControl.ShowElement(IconErrorMinScale);
                    return false;
                }
            }
            return true;

        }

        bool CheckMaxPointDouble()
        {
            string maxLonStr = TbMaxLon.Text;
            string maxLatStr = TbMaxLat.Text;
            bool isLonDouble = FormInputControl.DoubleStringChecker(maxLonStr);
            bool isLatDouble = FormInputControl.DoubleStringChecker(maxLatStr);
            if (isLonDouble && isLatDouble)
            {
                FormInputControl.HideElement(IconErrorMaxPoint);
                return true;
            }
            else
            {
                FormInputControl.ShowElement(IconErrorMaxPoint);
                return false;
            }
        }

        bool CheckMinPointDouble()
        {
            string minLonStr = TbMinLon.Text;
            string minLatStr = TbMinLat.Text;
            bool isLonDouble = FormInputControl.DoubleStringChecker(minLonStr);
            bool isLatDouble = FormInputControl.DoubleStringChecker(minLatStr);
            if (isLonDouble && isLatDouble)
            {
                FormInputControl.HideElement(IconErrorMinPoint);
                return true;
            }
            else
            {
                FormInputControl.ShowElement(IconErrorMinPoint);
                return false;
            }
        }

        bool CheckMinMaxPoint()
        {
            bool useClipping = (bool)ChkClipping.IsChecked;
            bool useExtent = (bool)RbByExtent.IsChecked;

            if (!useClipping || !useExtent)
            {
                return true;
            }

            if (CheckMaxPointDouble() && CheckMinPointDouble())
            {
                string maxLonStr = TbMaxLon.Text;
                string maxLatStr = TbMaxLat.Text;
                string minLonStr = TbMinLon.Text;
                string minLatStr = TbMinLat.Text;
                double maxLon = double.Parse(maxLonStr);
                double maxLat = double.Parse(maxLatStr);
                double minLon = double.Parse(minLonStr);
                double minLat = double.Parse(minLatStr);

                if (maxLon > minLon && maxLat > minLat)
                {
                    return true;
                }
                else
                {
                    FormInputControl.ShowElement(IconErrorMaxPoint);
                    FormInputControl.ShowElement(IconErrorMinPoint);
                    return false;
                }
            }
            else
            {
                return false;
            }
        }
        #endregion

        # region elements visibility
        void SetMaxScaleVisibility(Visibility visibility)
        {
            if (!_isInited)
                return;

            TbMaxScale.Visibility = visibility;
            TbkMaxScale.Visibility = visibility;
        }

        void SetMinScaleVisibility(Visibility visibility)
        {
            if (!_isInited)
                return;

            TbMinScale.Visibility = visibility;
            TbkMinScale.Visibility = visibility;
        }

        void SetClippingRadio(Visibility visibility)
        {
            if (!_isInited)
                return;

            RbByExtent.Visibility = visibility;
            RbByPolygon.Visibility = visibility;
        }

        void SetByExtentVisibility(Visibility visibility)
        {
            if (!_isInited)
                return;

            TbMaxLon.Visibility = visibility;
            TbMaxLat.Visibility = visibility;
            TbkMaxPoint1.Visibility = visibility;
            TbkMaxPoint2.Visibility = visibility;
            TbkMaxPoint3.Visibility = visibility;
            TbkMaxPoint4.Visibility = visibility;

            TbMinLon.Visibility = visibility;
            TbMinLat.Visibility = visibility;
            TbkMinPoint1.Visibility = visibility;
            TbkMinPoint2.Visibility = visibility;
            TbkMinPoint3.Visibility = visibility;
            TbkMinPoint4.Visibility = visibility;
        }

        void SetByPolygonVisibility(Visibility visibility)
        {
            if (!_isInited)
                return;

            TbPolygon.Visibility = visibility;
            TbkPolygon.Visibility = visibility;
        }
        #endregion

        # region handlers for visibility change
        private void ChkMaxScale_Checked(object sender, RoutedEventArgs e)
        {
            SetMaxScaleVisibility(Visibility.Visible);
        }

        private void ChkMaxScale_Unchecked(object sender, RoutedEventArgs e)
        {
            SetMaxScaleVisibility(Visibility.Collapsed);
        }

        private void ChkMinScale_Checked(object sender, RoutedEventArgs e)
        {
            SetMinScaleVisibility(Visibility.Visible);
        }

        private void ChkMinScale_Unchecked(object sender, RoutedEventArgs e)
        {
            SetMinScaleVisibility(Visibility.Collapsed);
        }

        private void ChkClipping_Unchecked(object sender, RoutedEventArgs e)
        {
            SetClippingRadio(Visibility.Collapsed);
            SetByExtentVisibility(Visibility.Collapsed);
            SetByPolygonVisibility(Visibility.Collapsed);
        }

        private void RbByExtent_Checked(object sender, RoutedEventArgs e)
        {
            SetByExtentVisibility(Visibility.Visible);
        }

        private void RbByExtent_Unchecked(object sender, RoutedEventArgs e)
        {
            SetByExtentVisibility(Visibility.Collapsed);
        }

        private void ChkClipping_Checked(object sender, RoutedEventArgs e)
        {
            SetClippingRadio(Visibility.Visible);
            if ((bool)RbByExtent.IsChecked)
            {
                SetByExtentVisibility(Visibility.Visible);
                SetByPolygonVisibility(Visibility.Collapsed);
            }
            else
            {
                SetByExtentVisibility(Visibility.Collapsed);
                SetByPolygonVisibility(Visibility.Visible);
            }
        }

        private void RbByPolygon_Checked(object sender, RoutedEventArgs e)
        {
            SetByPolygonVisibility(Visibility.Visible);
        }

        private void RbByPolygon_Unchecked(object sender, RoutedEventArgs e)
        {
            SetByPolygonVisibility(Visibility.Collapsed);
        }
        #endregion

        #region handers for input check
        private void TbOpacity_LostFocus(object sender, RoutedEventArgs e)
        {
            CheckOpacity();
        }

        private void TbMaxScale_LostFocus(object sender, RoutedEventArgs e)
        {
            CheckMaxMinScale();
        }

        private void TbMinScale_LostFocus(object sender, RoutedEventArgs e)
        {
            CheckMaxMinScale();
        }

        private void TbMaxLon_LostFocus(object sender, RoutedEventArgs e)
        {
            CheckMinMaxPoint();
        }

        private void TbMaxLat_LostFocus(object sender, RoutedEventArgs e)
        {
            CheckMinMaxPoint();
        }

        private void TbMinLon_LostFocus(object sender, RoutedEventArgs e)
        {
            CheckMinMaxPoint();
        }

        private void TbMinLat_LostFocus(object sender, RoutedEventArgs e)
        {
            CheckMinMaxPoint();
        }

        private void TbPolygon_LostFocus(object sender, RoutedEventArgs e)
        {

        }
        #endregion

    }
}
